#include <condition_variable>
#include <shared_mutex>
#include <queue>
#include <thread>
#include <iostream>

// 生产任务总数
constexpr int kItems = 10;

// 读写锁：读线程（消费者）可以并发持有共享锁，写线程（生产者）使用独占锁
std::shared_mutex sm;

// 支持任意 BasicLockable 的条件变量，能与 shared_mutex/自定义锁配合
std::condition_variable_any cv_any;

// 共享队列
std::queue<int> buffer;

// 结束信号
bool done = false;

void producer() {
    for (int i = 0; i < kItems; ++i) {
        {
            // 生产者需要写入队列，使用独占锁
            std::unique_lock<std::shared_mutex> ul(sm);
            buffer.push(i);
        } // 写完即解锁
        cv_any.notify_all(); // 唤醒所有消费者，因为可能多个消费者等待
    }

    {
        std::unique_lock<std::shared_mutex> ul(sm);
        done = true; // 设置结束标记
    }
    cv_any.notify_all(); // 再通知一次，确保所有等待线程都能检测到 done
}

void consumer(int id) {
    while (true) {
        // 先以共享锁方式读取状态（多个消费者可同时持有）
        std::shared_lock<std::shared_mutex> sl(sm);
        cv_any.wait(sl, [] { return !buffer.empty() || done; });

        if (!buffer.empty()) {
            // 需要写入(弹出)队列 -> 升级为独占锁：先解共享锁，再获取独占锁
            sl.unlock();
            std::unique_lock<std::shared_mutex> ul(sm);
            int item = buffer.front();
            buffer.pop();
            ul.unlock();

            std::cout << "consumer " << id << " got " << item << '\n';
        } else if (done) {
            // 没有数据且生产结束 -> 退出
            break;
        }
        // 循环继续，自动在下一次迭代重新获取共享锁
    }
}

int main() {
    std::thread p(producer);
    std::thread c1(consumer, 1);
    std::thread c2(consumer, 2);
    p.join();
    c1.join();
    c2.join();
}